# -*- coding:utf-8 -*-

"""
    将上传到７牛之后的文件数据信息更新保存到数据库
    * zip包命名格式：    V05S74,V1SHZ1_1.23_2.01_20160525.zip
        SN号前6位代表不同设备类型（多个使用逗号连接）_待升级版本_此包版本_升级包打包时间.zip
    需要将文件名的相应格式提取对应信息并存储到数据库
"""

import time, json
import tornado.web
from utils.routes import route
from utils import log as logger
from configure import config
from utils import mongo


@route('/file/update/?', 'file.update')
class UpdateFileHandler(tornado.web.RequestHandler):
    """ 更新上传到７牛之后的文件
    """
    db_name             = config.DB_NAME
    collection_name     = config.COLLECTION_DATAS

    def get(self):
        self.finish('not implement.')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        """ 上传文件
        * 返回值里code含义：    0 - 成功； 1 - 参数错误； 2 - 文件名格式出错； 3 - 文件已存在；　４－保存数据失败；
        """
        if not self.request.body:
            self.finish({'code': 1, 'info': 'params error!'})
            return
        
        datas = json.loads(self.request.body)
        filename = datas.get('filename', None)
        size = datas.get('size', None)
        md5 = datas.get('md5', None)
        change_logs = datas.get('change_logs', None)
        finger_point = datas.get('finger_point', None)
        download_url = datas.get('download_url', None)
 
        logger.info('body =', self.request.body, caller=self)
        logger.info('filename =', filename, 'size =', size, 'md5 =', md5,
                    'change_logs =', change_logs, 'finger_point =', finger_point,
                    'download_url =', download_url, caller=self)
        # 检查参数
        if not filename or not md5 or not change_logs or not finger_point or not download_url:
            self.finish({'code': 1, 'info': 'params error!'})
            return

        # 校验文件名是否正确
        ret, infos = yield tornado.gen.Task(self.check_filename, filename)
        if not ret:
            self.finish({'code': 2, 'info': infos})
            return

        # 校验文件是否已经存在数据库了
        ret, info = yield tornado.gen.Task(self.check_file_exist, infos, md5)
        if ret:
            self.finish({'code': 3, 'info': info})
            return

        # 保存到数据库
        infos['md5']            = md5
        infos['info']           = change_logs   # 更新日志
        infos['size']           = size          # 文件大小
        infos['finger_point']   = finger_point  # 指纹
        infos['scope']          = 'test'        # 设置域为测试环境，待确定可用后人工转为正式域
        infos['device_scope']   = "1"           # 仅限白名单设备
        infos['status']         = '0'           # 0为未激活状态，1为激活状态
        infos['download_url']   = download_url  # 下载地址
        infos['update_success'] = 0             # 更新成功次数
        infos['update_failed']  = 0             # 更新失败次数
        ret, info = yield tornado.gen.Task(self.save_2_mongo, infos)
        if ret:
            self.finish({'code': 0, 'info': info})
        else:
            self.finish({'code': 4, 'info': info})

    @tornado.gen.engine
    def check_filename(self, filename, callback):
        """ 校验文件名格式是否正确
        """
        l = filename[:-4].split('_')
        if len(l) != 4 or '' in l:
            callback((False, 'file name error 1!'))
            return
        sn_ids_str, ver_from, ver, create_time = l[0], l[1], l[2], l[3]

        sn_ids = sn_ids_str.split(',')
        if '' in sn_ids:
            callback((False, 'sn ids error!'))
            return
        try:
            # if int(ver_from.replace('.','')) >= int(ver.replace('.','')):
            #     callback((False, 'ver error!'))
            #     return
            if compareversion(ver_from, ver) >= 0:
                callback((False, 'ver error!'))
                return
        except:
            callback((False, 'ver error!'))
            return

        infos = {
            'filename':     filename,           # 文件名
            'sn_ids':       sn_ids,             # 包含的sn ids
            'sn_ids_str':   sn_ids_str,
            'ver_from':     ver_from,           # 上一个版本的版本号
            'ver':          ver,                # 版本号
            'create_time':  create_time,        # 创建包的时间
            'ts':           int(time.time()),   # 时间戳
        }
        callback((True, infos))

    @tornado.gen.engine
    def check_file_exist(self, infos, md5, callback):
        """ 根据文件md5来查询，是否已经存在此zip包
        """
        spec = {
                '$or': [
                        {
                            'md5':          md5
                        },
                        {
                            'filename':     infos['filename']
                        }
                       ]
                }
        d = yield tornado.gen.Task(mongo.find_one, config.DB_NAME, config.COLLECTION_DATAS, spec)
        logger.info('d =', d, caller=self)
        if d:
            callback((True, 'file exists!'))
        else:
            callback((False, 'ok'))

    @tornado.gen.engine
    def save_2_mongo(self, infos, callback):
        """ 保存数据到mongodb
        """
        d = yield tornado.gen.Task(mongo.insert, config.DB_NAME, config.COLLECTION_DATAS, infos)
        if d:
            callback((True, 'save success!'))
        else:
            callback((False, 'save failed!'))

def compareversion(version1, version2):
    i = 0
    result = 0

    version1_strs = version1.split(".")
    version2_strs = version2.split(".")

    while (i < 4 and not result):
        pos_result =  cmp(int(version1_strs[i]), int(version2_strs[i]))
        if pos_result:
            result = pos_result
        else:
            i += 1

    return result

# if __name__ == '__main__':
#     r = [{'ver':"0.7.1.10"}, {'ver':"0.7.1.0"}]
#     r.sort(lambda x,y:compareversion(x['ver'],y['ver']))
#     print r